import * as vscode from "vscode";
import path from "path";
import { readdirSync, readFileSync, statSync } from "fs";
import * as iconv from "iconv-lite";
import { getCurrentWorkspaceFolder } from "./functions";
import { mirServer, MirServerProvider } from "./extension";
// const fs = require("fs");
// const iconv = require("iconv-lite");

type VarType = { key: string; label: string; tooltip: string };

class VarsTreeItem extends vscode.TreeItem {
  key: string;
  constructor(varType: VarType, collapsibleState = vscode.TreeItemCollapsibleState.None) {
    super(varType.label, collapsibleState);
    this.tooltip = varType.tooltip;
    this.key = varType.key;
    const query = new URLSearchParams({ key: this.key, label: varType.label });
    this.resourceUri = vscode.Uri.from({
      scheme: "mirServer",
      authority: "varsUsed",
      path: "/",
      query: query.toString(),
    });
  }
}

export class VarsUsedTreeViewProvider implements vscode.TreeDataProvider<VarsTreeItem> {
  workspaceFolder: string = "";
  vars: Record<string, string[]> = {};
  rules = [/(?<![A-Za-z0-9])[PDMNSIGAUTJZ]\d{1,3}(?![A-Za-z0-9])/gi];
  labels: Record<string, string[]> = {
    P: ["P0-P999 (私人变量，数字型)", "关闭对话框重置为0。"],
    D: ["D0-D999 (私人变量，数字型)", "下线不保存.摇筛子变量."],
    M: ["M0-M999 (私人变量，数字型)", "下线不保存.切换地图清空."],
    N: ["N0-N999 (私人变量，数字型)", "下线不保存.小退归0."],
    S: ["S0-S999 (私人变量，字符型)", "下线不保存.小退归0."],
    I: ["I0-I999 (全局变量，数字型)", "不可保存，服务器重启自动重置为0。"],
    G: ["G0-G999 (全局变量，数字型)", "可保存。（存放在Mir200/GlobalVal.ini文件里面）"],
    A: ["A0-A999 (全局变量，字符型)", "可保存。（存放在Mir200/GlobalVal.ini文件里面）"],
    U: ["U0-U499 (私人变量，数字型)", "可保存。（存放在人物数据库Mir.db里面、值最大范围正负21亿）"],
    T: ["T0-T499 (私人变量，字符型)", "可保存。（存放在人物数据库Mir.db里面、字符长度256<1个字母为1字符、1汉字为2字符>）"],
    J: ["J0-J499 (私人变量，数字型)", "可保存,每晚自动12点重置,合区或关停服务器请错开00:00点即可。（存放在人物数据库Mir.db里面、值最大范围正负21亿）"],
    Z: [
      "Z0-J499 (私人变量，字符型)",
      "可保存,每晚自动12点重置,合区或关停服务器请错开00:00点即可。（存放在人物数据库Mir.db里面、自定义清理时间位于参数设置 - 时间控制,和J变量共清理时间）",
    ],
  };

  private _onDidChangeTreeData: vscode.EventEmitter<VarsTreeItem | undefined | null | void> = new vscode.EventEmitter<VarsTreeItem | undefined | null | void>();
  readonly onDidChangeTreeData: vscode.Event<VarsTreeItem | undefined | null | void> = this._onDidChangeTreeData.event;

  getTreeItem(element: VarsTreeItem): vscode.TreeItem | Thenable<vscode.TreeItem> {
    return element;
  }
  update(workspaceFolder: string) {
    this.vars = {};
    this.workspaceFolder = workspaceFolder;
    const dir = "Mir200/Envir"; // 可以动态传入
    const searchDir = path.join(workspaceFolder, dir);
    this.walk(searchDir, this.rules);
    this.refresh();
  }

  refresh() {
    this._onDidChangeTreeData.fire();
  }
  setVars(vars: string[]) {
    vars
      .map((name) => ({ key: name[0], name }))
      .forEach(({ key, name }) => {
        key = key.toUpperCase();
        name = name.toUpperCase();
        if (!this.vars[key]) {
          this.vars[key] = [];
        }
        if (!this.vars[key].includes(name)) {
          this.vars[key].push(name);
        }
      });
  }

  getChildren(element?: VarsTreeItem | undefined): vscode.ProviderResult<VarsTreeItem[]> {
    if (!element) {
      const keys = Object.keys(this.vars);
      const sort = keys.sort((a, b) => a.localeCompare(b));
      return sort.map((key) => {
        return new VarsTreeItem({ key, label: this.labels[key][0], tooltip: this.labels[key][1] }, vscode.TreeItemCollapsibleState.Collapsed);
      });
    }
    const sort = this.vars[element.key].sort((a, b) => {
      const an = parseInt(a.replace(/^[A-Z](\d+)$/, "$1"));
      const bn = parseInt(b.replace(/^[A-Z](\d+)$/, "$1"));
      return an - bn;
    });
    return sort.map((name) => new VarsTreeItem({ label: name, tooltip: "", key: "" }));
  }

  walk(currentPath: string, regExpArray: RegExp[]) {
    const files = readdirSync(currentPath);
    files.forEach((file) => {
      const fullPath = path.join(currentPath, file);
      const stat = statSync(fullPath);
      if (stat.isDirectory()) {
        this.walk(fullPath, regExpArray);
      } else if (fullPath.endsWith(".txt")) {
        const content = iconv.decode(readFileSync(fullPath), "gbk");
        const list = regExpArray.map((regExp) => content.match(regExp)).filter((v) => !!v);
        if (list && list.length) {
          this.setVars(list.flat());
        }
      }
    });
    return true;
  }

  static init(context: vscode.ExtensionContext) {}
}

export class varsUsedProvider implements MirServerProvider {
  activate() {
    const provider = new VarsUsedTreeViewProvider();
    vscode.window.onDidChangeActiveTextEditor(() => {
      const folder = getCurrentWorkspaceFolder();
      if (!folder?.uri.fsPath) {
        return;
      }
      if (provider.workspaceFolder !== folder.uri.fsPath) {
        provider.update(folder.uri.fsPath);
        vscode.commands.executeCommand("setContext", "showVariableView", true);
      }
    });

    mirServer.context.subscriptions.push(
      vscode.window.registerTreeDataProvider("mir-script-language.variable-view", provider),
      vscode.commands.registerCommand("mir-script-language.hide-variable-view", () => {
        vscode.commands.executeCommand("setContext", "showVariableView", false);
      }),
      vscode.commands.registerCommand("mir-script-language.show-variable-view", () => {
        vscode.commands.executeCommand("setContext", "showVariableView", true);
      }),
      vscode.commands.registerCommand("mir-script-language.refresh-variable-view", () => {
        const folder = getCurrentWorkspaceFolder();
        if (!folder?.uri.fsPath) {
          return;
        }
        provider.update(folder.uri.fsPath);
      })
    );
  }
}
